/*
 * CHttpServer.h
 *
 *  Created on: 2016-7-25
 *      Author: terry
 */

#ifndef CHTTPSERVER_H_
#define CHTTPSERVER_H_

#include "HttpServer.h"
#include "mongoose.h"
#include "TThread.h"
#include <string>
#include <map>


/**
 * HTTP服务器实现
 * 內建的URL:
 *  /upload 表示上传文件,
 *  /api/json/ 表示JSON HTTP API,
 *  /api/sys/password 表示修改密码
 *  /api/file 表示一般的动态响应
 *  /api/ws 表示 websocket
 *
 */
class CHttpServer: public HttpServer, comn::Thread
{
public:
	CHttpServer();
	virtual ~CHttpServer();


	virtual bool setWebRoot(const char* dirPath);

	virtual bool setUploadDir(const char* dirPath);

	virtual bool setUserFile(const char* filePath);

	virtual bool addDir(const char* url, const char* dirPath);

	virtual bool start(int port, HttpHandler* handler);

	virtual void stop();

	virtual bool isStarted();

	virtual void broadcast(const void *data, size_t len);

	virtual bool addJsonApi(const char* prefix);

public:
	void handleHttpEvent(struct mg_connection *nc, int ev, struct http_message *hm);

	void handleUpload(struct mg_connection *nc, int ev, void *ev_data);

	void handleDirEntry(struct mg_connection *nc, int ev, void *ev_data);

	void handleWebSocketFrame(struct mg_connection *nc, int ev, struct websocket_message* wm);

protected:
	virtual int run();
	virtual void doStop();

protected:
	void handleJsonApi(struct mg_connection* nc, struct http_message *hm, mg_str& str);
	void handleSysApi(struct mg_connection* nc, struct http_message *hm, mg_str& str);
	void handleFileApi(struct mg_connection* nc, struct http_message *hm, mg_str& str);

	void makeJsonResponse(mg_connection *nc, int code, const char *reason, const std::string& json);

	void makeResponse(mg_connection *nc, int code, const char *reason,
		const std::string& origin,
		const std::string& mime,
		const std::string& content);

	std::string	makeUploadPath(const char* filename);

	bool setupUser();

	std::string makeUser(const std::string& name, const std::string& realm, const std::string& passwd);

	bool resetUser(const std::string& name, const std::string& passwd);


	struct DirEntry
	{
		std::string url;
		std::string	dirPath;
		mg_serve_http_opts opts;

		DirEntry():
			opts()
		{
		}
	};

	typedef std::map< std::string, DirEntry>	DirEntryMap;

	bool findDirEntry(const char* url, DirEntry& entry);
	bool findDirEntry(struct mg_str& url, DirEntry& entry);


	typedef std::map< std::string, std::string>	PrefixMap;
	bool findPrefix(const struct mg_str& url, std::string& prefix);

protected:
	HttpHandler*	m_handler;
	std::string	m_webRoot;
	std::string m_port;
	std::string m_uploadDir;
	std::string m_userFile;

	struct mg_mgr	m_mgr;
	mg_serve_http_opts	m_opts;
	struct mg_connection*	m_connection;


	DirEntryMap	m_entryMap;

	PrefixMap	m_prefixMap;

};

#endif /* CHTTPSERVER_H_ */
